#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "strset.h"

#define T Strset_T

#define TABLESIZE 97

struct T{
	struct elem{
		struct elem *next;
		char str[1];
	}*table[TABLESIZE];
};

T Strset_new(void)
{
	T set = calloc(1, sizeof *set);
	assert(set);
	return set;
}

void Strset_free(T *set)
{
	int i;
	assert(set && *set);
	for(i = 0; i < TABLESIZE; i++)
	{
		struct elem *p, *q;
		for(p=(*set)->table[i]; p; p=q)
		{
			q=p->next;
			free(p);
		}
	}
	free(*set);
	*set=NULL;
}

static unsigned hash(char *str)
{
	unsigned h=0;
	while (*str)
		h=(h<<1)+*str++;
	return h;
}

void Strset_add(T set, char *str)
{
	int i;
	struct elem *p;
	assert(set);
	assert(str);
	
	i = hash(str)%TABLESIZE;
	for(p=set->table[i]; p; p=p->next)
		if(strcmp(str, p->str)==0)
			return;
	p=malloc(sizeof *p + strlen(str));
	assert(p);
	strcpy(p->str, str);
	p->next = set->table[i];
	set->table[i]=p;
}

void Strset_foreach(T set, void apply(char *str, void *cl), void *cl)
{
	int i;
	assert(set);
	assert(apply);
	for(i=0; i< TABLESIZE; i++)
	{
		struct elem *p;
		for(p=set->table[i]; p; p=p->next)
			apply(p->str, cl);
	}
}
